﻿namespace Summoner
{
    using UnityEngine;
    using System;

    public class AssetManager : IDisposable
    {
        private static AssetManager _instance = null;

        public AssetManager() { _instance = this; }

        /// <summary>
        /// Initilaize the Asset manager
        /// </summary>
        /// <param name="callback"></param>
        public static void Init(Action callback)
        {
            AssetObtainer.instance.Init(() => { if (callback != null) { callback(); } });
        }

        public static void Init()
        {
            AssetObtainer.instance.Init();
        }

        /// <summary>
        /// load gameobject async
        /// </summary>
        /// <param name="name"></param>
        /// <param name="callback"></param>
        public static void LoadGameObjectAsync(string name, Action<GameObject> callback)
        {
            AssetObtainer.instance.LoadAssetAsync(name, (obj) =>
            {
                GameObject go = (GameObject)obj;
                if (go != null) { if (callback != null) { callback(go); } }
                else { ULogger.LogError(string.Format("Load GameObject {0} failed !", name)); }
            });
        }

        /// <summary>
        /// load gameobject with parameters async
        /// </summary>
        /// <param name="name"></param>
        /// <param name="parameter"></param>
        /// <param name="callback"></param>
        public static void LoadGameObjectWithParameterAsync(string name, object parameter, Action<GameObject, object> callback)
        {
            AssetObtainer.instance.LoadAssetAsync(name, (obj) =>
            {
                GameObject go = (GameObject)obj;
                if (go != null) { if (callback != null) { callback(go, parameter); } }
                else { ULogger.LogError(string.Format("Load GameObject {0} failed !", name)); }
            }, parameter);
        }

        /// <summary>
        /// load gameobject sync
        /// </summary>
        /// <param name="name"></param>
        /// <returns></returns>
        public static GameObject LoadGameObjectSync(string name)
        {
            return (GameObject)AssetObtainer.instance.LoadAssetSync(name);
        }

        /// <summary>
        /// load sprite async
        /// </summary>
        /// <param name="name"></param>
        /// <param name="callback"></param>
        public static void LoadSpriteAsync(string name, Action<Sprite> callback)
        {
            AssetObtainer.instance.LoadAssetAsync(name, (obj)=>
            {
                if(obj != null)
                {
                    Sprite sp = ((GameObject)obj).GetComponent<Sprite>();
                    if(callback != null) { callback(sp); }
                }
                else { ULogger.LogError(string.Format("Load Sprite {0} failed !", name)); }
            });
        }

        /// <summary>
        /// load sprite sync
        /// </summary>
        /// <param name="name"></param>
        /// <returns></returns>
        public static Sprite LoadSpriteSync(string name)
        {
            return ((GameObject)AssetObtainer.instance.LoadAssetSync(name)).GetComponent<Sprite>();
        }

        /// <summary>
        /// load config with ext name
        /// </summary>
        /// <param name="name"></param>
        /// <param name="ext"></param>
        /// <param name="callback"></param>
        public static void LoadConfig(string name, Action<string> callback, string ext = ".json")
        {
            AssetObtainer.instance.LoadConfig(name, callback, ext);
        }

        /// <summary>
        /// load config content from assetbundle async
        /// </summary>
        /// <param name="name"></param>
        /// <param name="callback"></param>
        public static void LoadConfigAsync(string name, Action<string> callback)
        {
            AssetObtainer.instance.LoadAssetAsync(name, (obj) =>
            {
                if (obj != null)
                {
                    if (callback != null) { callback(((TextAsset)obj).text); }
                }
                else
                {
                    ULogger.LogError(string.Format("Load Texture {0} failed !", name));
                }
            });
        }

        /// <summary>
        /// load config content from assetbundle sync
        /// </summary>
        /// <param name="name"></param>
        /// <param name="callback"></param>
        /// <returns></returns>
        public static string LoadConfigSync(string name)
        {
            return ((TextAsset)AssetObtainer.instance.LoadAssetSync(name)).text;
        }

        /// <summary>
        /// load bytes from assetbundle async
        /// </summary>
        /// <param name="name"></param>
        /// <param name="callback"></param>
        public static void LoadBytesAsync(string name, Action<byte[]> callback)
        {
            AssetObtainer.instance.LoadAssetAsync(name, (obj) =>
            {
                if (obj != null)
                {
                    if (callback != null) { callback(((TextAsset)obj).bytes); }
                }
                else
                {
                    ULogger.LogError(string.Format("Load Texture {0} failed !", name));
                }
            });
        }

        /// <summary>
        /// load bytes from assetbundle sync
        /// </summary>
        /// <param name="name"></param>
        /// <param name="callback"></param>
        /// <returns></returns>
        public static byte[] LoadBytesSync(string name)
        {
            return ((TextAsset)AssetObtainer.instance.LoadAssetSync(name)).bytes;
        }

        /// <summary>
        /// load texture async
        /// </summary>
        /// <param name="name"></param>
        /// <param name="callback"></param>
        public static void LoadTextureAsync(string name, Action<Texture2D> callback)
        {
            AssetObtainer.instance.LoadAssetAsync(name, (obj)=>
            {
                if (obj != null)
                {
                    if (callback != null) { callback((Texture2D)obj); }
                }
                else
                {
                    ULogger.LogError(string.Format("Load Texture {0} failed !", name));
                }
            });
        }

        /// <summary>
        /// load texture2d sync
        /// </summary>
        /// <param name="name"></param>
        /// <returns></returns>
        public static Texture2D LoadTextureSync(string name)
        {
            return (Texture2D)AssetObtainer.instance.LoadAssetSync(name);
        }

        /// <summary>
        /// load scriptobject sync
        /// </summary>
        /// <param name="name"></param>
        /// <param name="callback"></param>
        public static void LoadScriptableObjectAsync(string name, Action<ScriptableObject> callback)
        {
            AssetObtainer.instance.LoadAssetAsync(name, (obj)=>
            {
                if(obj != null)
                {
                    if (callback != null) { callback((ScriptableObject)obj); }
                }
                else { ULogger.LogError(string.Format("Load ScriptableObject {0} failed !", name)); }
            });
        }

        /// <summary>
        /// load scriptobject sync
        /// </summary>
        /// <param name="name"></param>
        /// <returns></returns>
        public static ScriptableObject LoadScriptableObjectSync(string name)
        {
            return (ScriptableObject)AssetObtainer.instance.LoadAssetSync(name);
        }

        /// <summary>
        /// load png, tga or jpg file from server sync
        /// </summary>
        /// <param name="url"></param>
        /// <param name="callback"></param>
        public static void LoadImageAsync(string url, Action<Texture2D> callback)
        {
            AssetObtainer.instance.LoadImageAsync(url, callback);
        }

        /// <summary>
        /// delete asset
        /// </summary>
        /// <param name="obj"></param>
        public static void DeleteAsset(UnityEngine.Object obj)
        {
            AssetObtainer.instance.DeleteAsset(obj);
        }

        public static AssetManager Instance
        {
            get
            {
                if (_instance == null) { _instance = new AssetManager(); }
                return _instance;
            }
        }

        #region IDisposable Support
        private bool disposedValue = false; // 要检测冗余调用

        protected virtual void Dispose(bool disposing)
        {
            if (!disposedValue)
            {
                if (disposing)
                {
                    AssetObtainer.instance.Dispose();
                }
                disposedValue = true;
            }
        }

        // 添加此代码以正确实现可处置模式。
        public void Dispose()
        {
            // 请勿更改此代码。将清理代码放入以上 Dispose(bool disposing) 中。
            Dispose(true);
            GC.SuppressFinalize(this);
        }
        #endregion
    }
}